package com.hzzftech.watchdog.busi.controller;

import com.hzzftech.watchdog.busi.constants.BusiConstant;
import com.hzzftech.watchdog.busi.core.file.repository.FileRepositoryManager;
import com.hzzftech.watchdog.busi.core.file.repository.KtGitRepositoryFileParser;
import com.hzzftech.watchdog.busi.domain.KtFileRepository;
import com.hzzftech.watchdog.busi.domain.KtRepository;
import com.hzzftech.watchdog.busi.encrypt.DESEncrypt;
import com.hzzftech.watchdog.busi.service.IKtRepositoryFileService;
import com.hzzftech.watchdog.busi.service.IKtRepositoryService;
import com.hzzftech.watchdog.busi.utils.ZipUtil;
import com.hzzftech.watchdog.common.annotation.Log;
import com.hzzftech.watchdog.common.core.controller.BaseController;
import com.hzzftech.watchdog.common.core.domain.AjaxResult;
import com.hzzftech.watchdog.common.core.page.TableDataInfo;
import com.hzzftech.watchdog.common.enums.BusinessType;
import com.hzzftech.watchdog.common.exception.base.BaseException;
import com.hzzftech.watchdog.common.utils.StringUtils;
import com.hzzftech.watchdog.common.utils.poi.ExcelUtil;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * 文件资源库Controller
 * 
 * @author liquanxiang
 * @date 2021-11-27
 */
@Controller
@RequestMapping("/watchdog/repository")
public class KtRepositoryController extends BaseController
{
    private String prefix = "busi/repository";

    @Value("${kt-watchdog.DES_SECURITY_KEY}")
    private String DES_SECURITY_KEY;

    @Autowired
    private IKtRepositoryService ktRepositoryService;

    @Autowired
    private IKtRepositoryFileService fileService;

    public static final Logger logger = LoggerFactory.getLogger(KtRepositoryController.class);

    @Value("${kt-watchdog.git_file_repository_location}")
    private String REPOSITORY_ROOT;

    @GetMapping("/detail/{repoId}")
    public String repositoryDetail(@PathVariable("repoId") Long repoId, ModelMap mmap) {
        KtRepository ktRepository = ktRepositoryService.selectKtRepositoryByRepositoryId(repoId);
        mmap.put("repo", ktRepository);
        // 解析资源仓库。文件系统到数据库信息映射
        FileRepositoryManager manager = (new FileRepositoryManager(REPOSITORY_ROOT, ktRepository.getRepositoryLocation(), new KtGitRepositoryFileParser(fileService, repoId, null)));
        manager.parse();
        mmap.put("repoList", fileService.selectKtRepositoryByRepoId(repoId));
        return "busi/repository_file/repository_file";
    }

    @RequiresPermissions("busi:repository:view")
    @GetMapping()
    public String repository()
    {
        return prefix + "/repository";
    }

    /**
     * 查询文件资源库列表
     */
    @RequiresPermissions("busi:repository:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(KtRepository ktRepository)
    {
        startPage();
        List<KtRepository> list = ktRepositoryService.selectKtRepositoryList(ktRepository);
        list.forEach(e -> {
            if (e.getGitAuthType().equals(BusiConstant.AUTH_TYPE_SSH)) {
                e.setGitSshKey(BusiConstant.ENCRPT_STR);
                e.setGitPassword(null);
            } else if (e.getGitAuthType().equals(BusiConstant.AUTH_TYPE_PASS)) {
                e.setGitSshKey(null);
                e.setGitPassword(BusiConstant.ENCRPT_STR);
            }
        });
        return getDataTable(list);
    }

    /**
     * 导出文件资源库列表
     */
    @RequiresPermissions("busi:repository:export")
    @Log(title = "文件资源库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(KtRepository ktRepository)
    {
        List<KtRepository> list = ktRepositoryService.selectKtRepositoryList(ktRepository);
        ExcelUtil<KtRepository> util = new ExcelUtil<KtRepository>(KtRepository.class);
        return util.exportExcel(list, "文件资源库数据");
    }

    @RequiresPermissions("busi:repository:export")
    @Log(title = "文件资源库导出", businessType = BusinessType.EXPORT)
    @GetMapping("/exportRepo/{repoId}")
    public void exportRepo(@PathVariable("repoId") Long repoId, HttpServletResponse response) {
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        KtRepository repository = ktRepositoryService.selectKtRepositoryByRepositoryId(repoId);
        response.addHeader("Content-Disposition", "filename=" + repository.getRepositoryLocation()+".zip");
        if (repository != null) {
            File repof = new File(REPOSITORY_ROOT + File.separator + repository.getRepositoryLocation());
            if (repof.exists() && repof.isDirectory()) {
                try {
                    ZipUtil.toZip(repof.getAbsolutePath(), response.getOutputStream(), true);
                } catch (IOException e) {
                    logger.error("导出失败资源仓库失败", e);
                }
            }
        }
    }

    /**
     * 新增文件资源库
     */
    @GetMapping("/add")
    public String add( ModelMap mmap)
    {
        return prefix + "/add";
    }

    /**
     * 新增保存文件资源库
     */
    @RequiresPermissions("busi:repository:add")
    @Log(title = "文件资源库", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(KtRepository ktRepository)
    {
        String gitAuthType = ktRepository.getGitAuthType();
        if (gitAuthType.equals(BusiConstant.AUTH_TYPE_PASS)) {
            ktRepository.setGitSshKey(null);
            if (StringUtils.isEmpty(ktRepository.getGitUsername()) || StringUtils.isEmpty(ktRepository.getGitPassword())){
                return AjaxResult.error("git用户名或密码不能为空");
            }
            try {
                ktRepository.setGitPassword(DESEncrypt.encrypt(ktRepository.getGitPassword(), DES_SECURITY_KEY));
            } catch (Exception e) {
                logger.error("加密失败",e);
                return AjaxResult.error("git密码加密失败");
            }
        } else {
            ktRepository.setGitUsername(null);
            ktRepository.setGitPassword(null);
            if (StringUtils.isEmpty(ktRepository.getGitSshKey())) {
                return AjaxResult.error("SSH key 不能为空");
            }
            try {
                ktRepository.setGitSshKey(DESEncrypt.encrypt(ktRepository.getGitSshKey(), DES_SECURITY_KEY));
            } catch (Exception e) {
                logger.error("加密失败",e);
                return AjaxResult.error("SSH KEY加密失败");
            }
        }
        if (!ktRepositoryService.checkRespNameOnly(ktRepository.getRepositoryName())){
            return AjaxResult.error("资源仓库名已存在");
        }
        if (!ktRepositoryService.checkRespLocationOnly(ktRepository.getRepositoryLocation())) {
            return AjaxResult.error("资源仓库路径已存在");
        }
        ktRepositoryService.addCommHandle(ktRepository);
        return toAjax(ktRepositoryService.insertKtRepository(ktRepository));
    }

    /**
     * 修改文件资源库
     */
    @RequiresPermissions("busi:repository:edit")
    @GetMapping("/edit/{repositoryId}")
    public String edit(@PathVariable("repositoryId") Long repositoryId, ModelMap mmap)
    {
        KtRepository ktRepository = ktRepositoryService.selectKtRepositoryByRepositoryId(repositoryId);
        if (ktRepository.getGitAuthType().equals(BusiConstant.AUTH_TYPE_PASS)) {
            ktRepository.setGitPassword(BusiConstant.ENCRPT_STR);
        } else if (ktRepository.getGitAuthType().equals(BusiConstant.AUTH_TYPE_SSH)){
            ktRepository.setGitSshKey(BusiConstant.ENCRPT_STR);
        } else {
            throw new BaseException("未知异常");
        }
        mmap.put("ktRepository", ktRepository);
        return prefix + "/edit";
    }

    /**
     * 修改保存文件资源库
     */
    @RequiresPermissions("busi:repository:edit")
    @Log(title = "文件资源库", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(KtRepository ktRepository)
    {
        if (ktRepository.getRepositoryId() == null) {
            throw new BaseException("未知异常");
        }
         String gitAuthType = ktRepository.getGitAuthType();
        KtRepository ktRepositoryDB = ktRepositoryService.selectKtRepositoryByRepositoryId(ktRepository.getRepositoryId());
        if (gitAuthType.equals(BusiConstant.AUTH_TYPE_PASS)) {
            ktRepository.setGitSshKey(null);
            if (StringUtils.isEmpty(ktRepository.getGitUsername()) || StringUtils.isEmpty(ktRepository.getGitPassword())){
                return AjaxResult.error("git用户名或密码不能为空");
            }
            try {
                if (ktRepository.getGitPassword().equals(BusiConstant.ENCRPT_STR)) {
                    ktRepository.setGitPassword(ktRepositoryDB.getGitPassword());
                } else {
                    ktRepository.setGitPassword(DESEncrypt.encrypt(ktRepository.getGitPassword(), DES_SECURITY_KEY));
                }
            } catch (Exception e) {
                logger.error("加密失败",e);
                return AjaxResult.error("git密码加密失败");
            }
        } else {
            ktRepository.setGitUsername(null);
            ktRepository.setGitPassword(null);
            if (StringUtils.isEmpty(ktRepository.getGitSshKey())) {
                return AjaxResult.error("SSH key 不能为空");
            }
            try {
                if (ktRepository.getGitSshKey().equals(BusiConstant.ENCRPT_STR)) {
                    ktRepository.setGitSshKey(ktRepositoryDB.getGitSshKey());
                } else {
                    ktRepository.setGitSshKey(DESEncrypt.encrypt(ktRepository.getGitSshKey(), DES_SECURITY_KEY));
                }
            } catch (Exception e) {
                logger.error("加密失败",e);
                return AjaxResult.error("SSH KEY加密失败");
            }
        }
        ktRepositoryService.updateCommHandle(ktRepository);
        return toAjax(ktRepositoryService.updateKtRepository(ktRepository));
    }

    /**
     * 删除文件资源库
     */
    @RequiresPermissions("busi:repository:remove")
    @Log(title = "文件资源库", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        int res = ktRepositoryService.deleteKtRepositoryByRepositoryIds(ids);
        if (-1 == res) {
            return AjaxResult.error("删除失败，有任务引用了该仓库");
        }
        return toAjax(res);
    }

    @RequiresPermissions("watchdog:repository_log:updateRepository")
    @Log(title = "文件资源库操作日志", businessType = BusinessType.DELETE)
    @GetMapping( "/updateRepository/{repositoryId}")
    @ResponseBody
    public AjaxResult updateRepository(@PathVariable("repositoryId") Long repositoryId) {
        return ktRepositoryService.updateGitResources(repositoryId) ? AjaxResult.success() : AjaxResult.error("更新失败");
    }


    @RequiresPermissions("watchdog:repository_log:forceUpdateRepository")
    @Log(title = "文件资源库强制更新", businessType = BusinessType.DELETE)
    @GetMapping( "/forceUpdateRepository/{repositoryId}")
    @ResponseBody
    public AjaxResult forceUpdateRepository(@PathVariable("repositoryId") Long repositoryId) {
        boolean is = ktRepositoryService.forceUpdateGitResources(repositoryId);
        if (is) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error("强制更新失败");
        }
    }

    @RequiresPermissions("watchdog:repository_log:allBranch")
    @Log(title = "文件资源库分支", businessType = BusinessType.DELETE)
    @GetMapping( "/allBranch/{repositoryId}")
    @ResponseBody
    public AjaxResult allGItBranch(@PathVariable("repositoryId") Long repositoryId) {
        List<String> allBranch = ktRepositoryService.findAllBranch(repositoryId);
        if (Objects.isNull(allBranch) || allBranch.size() == 0) {
            return AjaxResult.error("获取分支失败");
        } else {
            return AjaxResult.success(allBranch);
        }
    }
}
